%{
#include <ctype.h>
#include <stdio.h>
#define YYSTYPE double
%}

%start program

%token LT
%token LE
%token EQ
%token NE
%token GT
%token GE
%token IF
%token THEN
%token ELSE
%token ID
%token NUMERO
%token RELOP 
%token FLOAT
%token VAR 
%token CONST 
%token TYPE 
%token PROGRAM 
%token INICIO 
%token FIM 
%token FOR 	
%token WHILE 
%token DO 
%token TO 
%token DOWNTO 
%token STEP 
%token REPEAT 
%token UNTIL 
%token CASE 
%token FUNCTION 
%token PROCEDURE 
%token ASPECT 
%token BEFORE 
%token AFTER 
%token WRITELN 
%token READLN 
%token RECORD 
%token ARRAY 
%token RANGE 
%token TRUE 
%token FALSE 
%token BOOLEAN 
%token REAL 
%token INTEGER 
%token STRING_TYPE 
%token CHAR_TYPE 
%token STRING_TERM 
%token CHAR_TERM 
%token POINTER
%token POINTER_DEC 
%token POINTER_VAR 
%token OP_ARITMETICO 
%token ATRIBUICAO 
%token DOISPONTOS 
%token PONTO 
%token VIRGULA 
%token PONTOEVIRGULA 
%token ABRECOL 
%token FECHACOL 
%token ABREPAR 
%token FECHAPAR 
%token CONST_ATRIB
%token MAIS 
%token MULT 
%token DIV 
%token MOD 
%token MENOS 
%token NAO 
%token OP_LOGICO 
%token EE 
%token OU 
%token OF

%%

literal : CHAR_TERM | NUMERO  
	;

program		: PROGRAM ID PONTOEVIRGULA program_body PONTO {printf("Sucesso!\n");}
		;

program_body 	: const_section 
		;
	
const_section 	: const_decl PONTOEVIRGULA type_section 
		| type_section 
		;

type_section 	: type_decl PONTOEVIRGULA var_section
		| var_section  
		;
	
var_section 	: var_decl PONTOEVIRGULA proc_fun_section
		| proc_fun_section
		;
	
proc_fun_section: proc_fun_decl PONTOEVIRGULA aspect_section
		| aspect_section
		;

aspect_section	: aspect_decl PONTOEVIRGULA before_after_list PONTOEVIRGULA bloco
		| bloco
		;

const_decl : CONST ID CONST_ATRIB literal 
           | const_decl PONTOEVIRGULA ID ATRIBUICAO literal 
           ;
	
type_decl  : TYPE ID CONST_ATRIB type_st
	   | type_decl PONTOEVIRGULA ID ATRIBUICAO type_st
	   ;
 
var_decl   	: VAR ID DOISPONTOS tipo
		| var_decl PONTOEVIRGULA ID DOISPONTOS tipo
		;

proc_fun_decl	: proc_fun_decl PROCEDURE procedure
		| proc_fun_decl FUNCTION function
		|
		;

procedure	: proc_or_func1 proc_or_func2
		;

function	: proc_or_func1 DOISPONTOS tipo proc_or_func2
		;

proc_or_func1	: ID ABREPAR parametros FECHAPAR
		| ID ABREPAR FECHAPAR
		| ID
		;

parametros	: VAR ID DOISPONTOS tipo
		| parametros PONTOEVIRGULA VAR ID DOISPONTOS tipo
		| ID DOISPONTOS tipo
		| parametros PONTOEVIRGULA ID DOISPONTOS tipo
		;

proc_or_func2	: PONTOEVIRGULA subprogram_const
		;

subprogram_const : const_decl PONTOEVIRGULA subprogram_var
		 | subprogram_var
		 ;

subprogram_var  : var_decl PONTOEVIRGULA bloco
	  	| bloco
		;
		
aspect_decl :
    ASPECT ID bloco | aspect_decl PONTOEVIRGULA ID bloco;

before_after : 
    BEFORE ID DOISPONTOS ID | AFTER ID DOISPONTOS ID ;

before_after_list :
    before_after | before_after_list PONTOEVIRGULA before_after ; 

type_st	: RECORD record_fields
	| POINTER pointer_tipo
	| tipo
	;

record_fields 	: campo_decl FIM
		;

campo_decl	: campo_decl PONTOEVIRGULA ID DOISPONTOS type_st
		| ID DOISPONTOS type_st
		;
	
pointer_tipo	: REAL
		| INTEGER
		| CHAR_TYPE
		| BOOLEAN
		| STRING_TYPE
		| ID
		;
	
tipo	: tipo2 REAL
	| tipo2 INTEGER
	| tipo2 CHAR_TYPE
	| tipo2 BOOLEAN
	| tipo2 STRING_TYPE
	| tipo2 ID
	;

tipo2	: tipo2 ARRAY array_range OF
	|
	;

array_range	: array_range ABRECOL NUMERO RANGE NUMERO FECHACOL
		| ABRECOL NUMERO RANGE NUMERO FECHACOL
		;		

valor	: NUMERO
	| FLOAT
	| STRING_TERM
	| CHAR_TERM
	| TRUE
	| FALSE
	;

bloco	: INICIO sec_instrucao FIM
	| INICIO FIM
	;
	
sec_instrucao	: sec_instrucao PONTOEVIRGULA instrucao
		| instrucao
		;

instrucao	: if
		| while
		| for
		| repeat
		| case
		| ID ABREPAR parametros_entrada FECHAPAR
		| bloco
		|
		| ID ABREPAR FECHAPAR
		| atribuicao
		;

if	: IF expressao THEN instrucao
	| IF expressao THEN instrucao ELSE instrucao
	;
	
while	: WHILE expressao DO instrucao
	;
	
for	: FOR ID ATRIBUICAO expressao TO expressao DO instrucao
	| FOR ID ATRIBUICAO expressao DOWNTO expressao DO instrucao
	;

repeat	: REPEAT instrucao UNTIL expressao
	;

case	: CASE expressao OF valor DOISPONTOS case2 case_inst FIM PONTOEVIRGULA
	| CASE expressao OF valor DOISPONTOS case2 case_inst ELSE instrucao FIM PONTOEVIRGULA
	;

case2 : instrucao ;

case_inst	: case_inst valor DOISPONTOS atribuicao PONTOEVIRGULA
		| valor DOISPONTOS atribuicao PONTOEVIRGULA
		;

parametros_entrada	: parametros_entrada PONTOEVIRGULA expressao
			| expressao
			;

atribuicao	: elem_variavel ATRIBUICAO expressao
		;

simu	: tios
	| colEx
	| elem_var
	| simu tios
	| simu colEx
	| simu elem_var
	;

tios	: tios POINTER
	| POINTER
	;

colEx	: colEx ABRECOL expressao FECHACOL
	| ABRECOL expressao FECHACOL
	;
	
elem_var	: ID simu
		;

elem_variavel	: ID
		| ID ABREPAR FECHAPAR
		| ID ABREPAR parametros_entrada FECHAPAR
		| ID simu
		| ID ABREPAR FECHAPAR simu
		| ID ABREPAR parametros_entrada FECHAPAR simu
		;
		
op_bin	: MAIS
	| MENOS
	| OP_ARITMETICO
	| OP_LOGICO
	| RELOP
	;	 

expressao 	: MENOS ABREPAR expressao FECHAPAR
		| NAO ABREPAR expressao FECHAPAR
		| ABREPAR expressao FECHAPAR
		| MENOS valor
		| NAO valor
		| valor
		| MENOS elem_variavel
		| NAO elem_variavel
		| elem_variavel
		| MENOS ABREPAR expressao FECHAPAR op_bin expressao
		| NAO ABREPAR expressao FECHAPAR op_bin expressao
		| ABREPAR expressao FECHAPAR op_bin expressao
		| MENOS valor op_bin expressao
		| NAO valor op_bin expressao
		| valor op_bin expressao
		| MENOS elem_variavel op_bin expressao
		| NAO elem_variavel op_bin expressao
		| elem_variavel op_bin expressao
		;

%%

#include "lex.yy.c"


int main() {
    yyparse();
    return 0;

}


